﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;

namespace AutoF3
{
    public partial class AddProblemForm : Form
    {
        List<Problem> problems;
        SheetBuilder sb;
        int indexToEdit = -1;
        int numDollarSignsProblemBox = 0;
        int numDollarSignsSolutionsBox = 0;

        public AddProblemForm(List<Problem> problems, SheetBuilder sb)
        {
            InitializeComponent();
            this.problems = problems;
            this.sb = sb;
            BuildControls();
            HighlightTexCode(problemTextBox);
            HighlightTexCode(solutionsTextBox);
        }

        public AddProblemForm(List<Problem> problems, SheetBuilder sb, int indexOfProblemToEditInSheetBuilder) //TODO: do we even need the list of problems?
        {
            InitializeComponent();
            this.problems = problems;
            this.sb = sb;
            this.indexToEdit = indexOfProblemToEditInSheetBuilder;
            BuildFinalizedControls();
            HighlightTexCode(problemTextBox);
            HighlightTexCode(solutionsTextBox);
        }

        private void BuildControls()
        {
            foreach (var problem in problems)
                problemListBox.Items.Add(problem.problemName);

            var currProblem = problems[Math.Max(0, problemListBox.SelectedIndex)];
            problemTextBox.Text = currProblem.problemText;
            problemWebBrowser.DocumentText = ConvertTexToHtml.ConvertToHtml(problemTextBox.Text);

            BuildSolutionsControls(currProblem);
        }

        private void BuildSolutionsControls(Problem problem)
        {
            solutionsListBox.Items.Clear();
            solutionsTextBox.Clear();

            var currSolutionsList = problem.GetPossibleSolutionsList();
            var currProblemHasSolutions = currSolutionsList.Count > 0;

            if (currProblemHasSolutions)
            {
                for (int i = 0; i < currSolutionsList.Count; i++)
                    solutionsListBox.Items.Add("Possible Solution #" + (i + 1));
                solutionsTextBox.Text = currSolutionsList[0];
            }
            else
            {
                solutionsListBox.Items.Add("User-generated Solution");
            }

            solutionsWebBrowser.DocumentText = ConvertTexToHtml.ConvertToHtml(solutionsTextBox.Text);
        }

        private void BuildFinalizedControls()
        {
            var problem = sb.problemList[indexToEdit];
            var finalizedProblem = sb.finalizedProblemList[indexToEdit];

            problemListBox.Items.Add(problem.problemName);
            problemTextBox.Text = finalizedProblem.problemText;
            problemWebBrowser.DocumentText = ConvertTexToHtml.ConvertToHtml(problemTextBox.Text);

            BuildFinalizedSolutionsControls(problem, finalizedProblem);
        }

        private void BuildFinalizedSolutionsControls(Problem problem, FinalizedProblem finalizedProblem)
        {
            solutionsListBox.Items.Clear();
            solutionsTextBox.Clear();

            var currSolutionsList = problem.GetPossibleSolutionsList();
            var currProblemHasOtherSolutions = currSolutionsList.Count > 0;

            solutionsListBox.Items.Add("User-Chosen Solution");
            solutionsTextBox.Text = finalizedProblem.solutionText;
            solutionsWebBrowser.DocumentText = ConvertTexToHtml.ConvertToHtml(solutionsTextBox.Text);

            if (currProblemHasOtherSolutions)
                for (int i = 0; i < currSolutionsList.Count; i++)
                    solutionsListBox.Items.Add("Possible Solution #" + (i + 1));
        }

        private void problemListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = problemListBox.SelectedIndex;

            if (index >= 0)
            {
                var currProblem = problems[problemListBox.SelectedIndex];
                problemTextBox.Text = currProblem.problemText;
                problemWebBrowser.DocumentText = ConvertTexToHtml.ConvertToHtml(problemTextBox.Text);
                BuildSolutionsControls(currProblem);
            }
        }

        private void solutionsListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = solutionsListBox.SelectedIndex;

            if (indexToEdit >= 0)
            {
                if (index == 0)
                {
                    solutionsTextBox.Text = sb.finalizedProblemList[indexToEdit].solutionText;
                    return;
                }
                else
                    index--;
            }

            if (index >= 0)
            {
                solutionsTextBox.Clear();

                var currProblem = problems[Math.Max(0, problemListBox.SelectedIndex)];
                var currSolutionsList = currProblem.GetPossibleSolutionsList();
                var currProblemHasSolutions = currSolutionsList.Count > 0;

                if (currProblemHasSolutions)
                    solutionsTextBox.Text = currSolutionsList[index];
            }

            solutionsWebBrowser.DocumentText = ConvertTexToHtml.ConvertToHtml(solutionsTextBox.Text);
        }

        private void updateButton_Click(object sender, EventArgs e)
        {
            var currProblem = problems[Math.Max(0, problemListBox.SelectedIndex)];
            var solutionIndex = solutionsListBox.SelectedIndex;

            if (indexToEdit >= 0)
            {
                if (solutionIndex == 0)
                    solutionIndex = sb.finalizedProblemList[indexToEdit].solutionIndex;
                else
                    solutionIndex--;
            }

            var currFinalizedProblem = new FinalizedProblem(problemTextBox.Text, solutionsTextBox.Text, Math.Max(0, solutionIndex));

            if (indexToEdit >= 0)
                sb.SetAtIndex(indexToEdit, currProblem, currFinalizedProblem);
            else
                sb.Add(currProblem, currFinalizedProblem);

            this.Close();
        }

        private void problemTextBox_TextChanged(object sender, EventArgs e)
        {
            int numDollarSigns = CountNumberOfDollarSigns(problemTextBox.Text);
            if (numDollarSignsProblemBox != numDollarSigns)
            {
                numDollarSignsProblemBox = numDollarSigns;
                HighlightTexCode(problemTextBox);
            }
        }

        private void solutionsTextBox_TextChanged(object sender, EventArgs e)
        {
            int numDollarSigns = CountNumberOfDollarSigns(solutionsTextBox.Text);
            if (numDollarSignsSolutionsBox != numDollarSigns)
            {
                numDollarSignsSolutionsBox = numDollarSigns;
                HighlightTexCode(solutionsTextBox);
            }
        }

        private int CountNumberOfDollarSigns(string text)
        {
            return text.Count(c => c == '$');
        }

        public void HighlightTexCode(RichTextBox rtb)
        {
            int oldCaretPosition = rtb.SelectionStart;

            rtb.SelectionStart = 0;
            rtb.SelectionLength = rtb.Text.Length;
            rtb.SelectionColor = Color.Black;

            var list = Parse(rtb.Text);
            Highlight(rtb, list);

            rtb.SelectionLength = 0;
            rtb.SelectionStart = oldCaretPosition;
        }

        private List<SelectedTextInfo> Parse(string text) 
        {
            var list = new List<SelectedTextInfo>();

            string regex = "(\\$\\$.*?\\$\\$)|(\\$.*?\\$)|(\\$\\$[^\\$]*?$)|(\\$[^\\$]*?$)";
            RegexOptions options = (RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline);

            Regex reg = new Regex(regex, options);

            var matches = reg.Matches(text);
            foreach (Match match in matches)
                list.Add(new SelectedTextInfo(match.Index, match.Length));
        
            return list;
        }

        private void Highlight(RichTextBox rtb, List<SelectedTextInfo> texList) 
        {
            int length = rtb.Text.Length;

            foreach (var info in texList)
            {
                rtb.SelectionStart = info.startIndex;
                rtb.SelectionLength = Math.Min(info.length, length - info.startIndex);
                rtb.SelectionColor = Color.Brown;
            }
        }

        private void AddProblemForm_Resize(object sender, EventArgs e)
        {
            int width = this.Width;
            int height = this.Height;
            if (width % 2 == 1)
                width--;

            //button position
            updateButton.Location = new Point(width - 127, height - 73);

            //richTextBoxes and tabbed controls
            int tabControlWidth = (width - 414) / 2;
            int tabControlHeight = height - 91;

            tabControl2.Location = new Point(386 + tabControlWidth, 12);

            tabControl1.Size = new Size(tabControlWidth, tabControlHeight);
            tabControl2.Size = new Size(tabControlWidth, tabControlHeight);

            //labels
            label2.Location = new Point(199 + tabControlWidth, 9);

            //listBoxes
            solutionsListBox.Location = new Point(202 + tabControlWidth, 25);

            int numRows = (height - 104 - 4) / 13;
            int listBoxHeight = numRows * problemListBox.ItemHeight + 4;

            problemListBox.Size = new Size(178, listBoxHeight);
            solutionsListBox.Size = new Size(178, listBoxHeight);
        }

        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (tabControl1.SelectedIndex == 0)
                problemWebBrowser.DocumentText = ConvertTexToHtml.ConvertToHtml(problemTextBox.Text);
        }

        private void tabControl2_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (tabControl2.SelectedIndex == 0)
                solutionsWebBrowser.DocumentText = ConvertTexToHtml.ConvertToHtml(solutionsTextBox.Text);
        }
    }
}
